package com.erpoa.service.impl;

import com.alibaba.fastjson.JSON;
import com.erpoa.annotation.DataBase;
import com.erpoa.constants.DataSourceNames;
import com.erpoa.dto.WareHouseMaterialDto;
import com.erpoa.entity.BarCodeEntity;
import com.erpoa.entity.PackMessage;
import com.erpoa.mapper.WareHouseMaterialMapper;
import com.erpoa.service.WareHouseMaterialService;
import com.erpoa.utils.PDAException;
import com.erpoa.utils.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;

/**
 * @author chenjimin
 * @Title: WareHouseMaterialServiceImpl
 * @ProjectName oaerp
 * @Description: TODO
 * @date 2020/9/159:48
 */
@Service
public class WareHouseMaterialServiceImpl implements WareHouseMaterialService {
    ThreadLocal<Long> longThreadLocal = ThreadLocal.withInitial(() -> {

        return Thread.currentThread().getId();
    });

    @Autowired
    private WareHouseMaterialMapper wareHouseMaterialMapper;

    @Override
    @DataBase(DataSourceNames.DSX5)
    @Transactional()
    public List<WareHouseMaterialDto> getMaterialList(PackMessage packMessage) {
        // liujiajie 2019-02-25 获取用户级别权限tc_pgen_file 添加用户仓库权限

        String wareUser = this.wareHouseMaterialMapper.selectpgenByHrNo(packMessage.getUser().getsCode());
        if (StringUtil.isEmpty(wareUser)) {
            throw new PDAException("当前用户：" + packMessage.getUser().getsCode() + ",没有仓库权限！");
        }

        List<WareHouseMaterialDto> materialDtos = wareHouseMaterialMapper.selectOrderplanByDataPermisoon(wareUser, packMessage.getMachine(), packMessage.getUser().getsCode());
        List<WareHouseMaterialDto> materialDtotemp = new ArrayList<>();
        for (WareHouseMaterialDto materialDto : materialDtos
        ) {
            if (!("笔头".equals(materialDto.getType()) || "硅油".equals(materialDto.getType()) || "油墨".equals(materialDto.getType()))) {
                materialDtotemp.add(materialDto);
            }
        }


        if (StringUtil.isEmpty(materialDtotemp)) {
            throw new PDAException("当前机台：" + packMessage.getMachine() + "，没有有效的数据");
        }

        return materialDtotemp;

    }

    @Override
    @DataBase(DataSourceNames.DSX5)
    @Transactional()
    public String queryMachineCodeOrBarCode(PackMessage packMessage) {
        int machNum = this.wareHouseMaterialMapper.countMachNum(packMessage.getBarcode());
        if (machNum > 0) {
            return "机台";
        }

        String matCode = this.wareHouseMaterialMapper.selectFmatCodeByBarCode(StringUtil.replaceBlank(packMessage.getBarcode()));

        if (StringUtil.isEmpty(matCode)) {
            throw new PDAException("请确认扫描的机台或条码！");
        }

        return matCode;
        // return "BGR6408BK8423711";
    }

    @Override
    @DataBase(DataSourceNames.DSX5)
    @Transactional()
    public String materialBusiness(PackMessage packMessage) {
        BarCodeEntity barCodeEntity;
        barCodeEntity = (BarCodeEntity) JSON.parseObject(packMessage.getMessage(), BarCodeEntity.class);
        int count = this.wareHouseMaterialMapper.countMesfunctionalByParam(barCodeEntity.getfFactoryCode(), barCodeEntity.getfWorkShopCode());
        if (count > 0) {
            return "Y";
        }
        return "N";
    }

    @Override
    @DataBase(DataSourceNames.DSX5)
    @Transactional(isolation = Isolation.SERIALIZABLE)
    public synchronized void jumpMaterialHandoverFragment(PackMessage packMessage) {

        BarCodeEntity barCodeEntity = JSON.parseObject(packMessage.getMessage(), BarCodeEntity.class);
        // 仓库发料共有方法
        String message = this.wareHouseMAterialCommon(packMessage, barCodeEntity);
        if ("N".equals(message.split("##")[0])) {
            throw new PDAException(message.split("##")[1]);
        }
        // 查询仓库和库位名称
        String fWareName, fSeatName = "";
        HashMap fsTemp = this.wareHouseMaterialMapper.selectSeatByParam(barCodeEntity.getfWareCode(), barCodeEntity.getfSeatCode());
        if (StringUtil.isEmpty(fsTemp)) {
            throw new PDAException("仓库库位名称获取失败");
        }
        fWareName = fsTemp.get("FWARENAME").toString();
        fSeatName = fsTemp.get("FSEATNAME") == null ? "" : fsTemp.get("FSEATNAME").toString();
        String dataSource = queryDataSource(packMessage);
        String uuid = "PDA" + UUID.randomUUID().toString().toString();
        if ("领料".equals(barCodeEntity.getfType())) {
            String amMessage = this.acquisitionMethod(barCodeEntity, dataSource);
            if (amMessage != null) {
                throw new PDAException(amMessage);
            }
        } else if ("超领".equals(barCodeEntity.getfType())) {
            String samMessage = this.superAcquisitionMethod(barCodeEntity, dataSource);
            if (samMessage != null) {
                throw new PDAException(samMessage);
            }
        }
        //TODO  CJM需要设置串行化 ，同一事物查询？
        // 插入领退料明细表
        int insertNum = this.wareHouseMaterialMapper.insertRdByParam(uuid, barCodeEntity.getfWeight(), packMessage.getUser().getsCode(),
                barCodeEntity.getfWareCode(), fWareName, barCodeEntity.getfSeatCode(), fSeatName,
                barCodeEntity.getfPlanID());
        if (insertNum <= 0) {
            throw new PDAException("插入明细表失败");
        }
        // 更新领退料表
        int updateNum = this.wareHouseMaterialMapper.updateRdMatByParam(barCodeEntity.getfWeight(), packMessage.getUser().getsCode(),
                barCodeEntity.getfWareCode(), fWareName, barCodeEntity.getfSeatCode(), fSeatName,
                barCodeEntity.getfPlanID());
        if (updateNum <= 0) {
            throw new PDAException("更新领退料表失败");
        }
        // 需要物料交接
        if ("Y".equals(packMessage.getCrashLog())) {
            int updateRMDNum = this.wareHouseMaterialMapper.updateRmdByParam(packMessage.getJobnum(), uuid);
            if (updateRMDNum <= 0) {
                throw new PDAException("物料交接回写失败!");
            }
        }
        // TODO     这种做法意义何在？？？？ 查询是否已经插入了中间表

        /*int x5idCount = this.wareHouseMaterialMapper.countX5IdbYUUID(uuid);
        if (x5idCount > 0) {
            throw new PDAException("本次提交的数据已经存在erp接口表");
        }*/
        int insertXFSQLNum = this.wareHouseMaterialMapper.insertXfByParam(uuid, Double.valueOf(barCodeEntity.getfWeight()), packMessage.getUser().getsCode(),
                barCodeEntity.getfWareCode(), barCodeEntity.getfSeatCode());
        if (insertXFSQLNum <= 0) {
            throw new PDAException("插入erp接口表失败！");
        }
        //  throw new PDAException("回退操作！");
    }

    /**
     * 超领
     *
     * @param barCodeEntity
     * @param dataSource
     * @return
     */
    private String superAcquisitionMethod(BarCodeEntity barCodeEntity, String dataSource) {
        // 1.料是否发满
        double fqty2 = this.wareHouseMaterialMapper.selectSfa2ByParam(dataSource, barCodeEntity.getfOrderNo(),
                barCodeEntity.getfMatCode(), barCodeEntity.getfProcessCode());

        if (fqty2 != 0) {
            throw new PDAException("料没发满，不允许做超领");
        }
        // 2.是否走超领审核
        int count4 = this.wareHouseMaterialMapper.countMesFunByParam(barCodeEntity.getfFactoryCode(), barCodeEntity.getfWorkShopCode());

        if (!barCodeEntity.getfUnit().equals("Y") && count4 <= 0) {
            throw new PDAException("该料未做超领审核或配置表不存在该超领权限");
        }

        return null;
    }


    private String acquisitionMethod(BarCodeEntity barCodeEntity, String dataSource) {
        // 1. 发料时，不能超工单应发
        // (1)查询sfa_file表工单级管控
        // 应发
        double num = this.wareHouseMaterialMapper.selectsfaByParam(dataSource, barCodeEntity.getfOrderNo(),
                barCodeEntity.getfMatCode(), barCodeEntity.getfProcessCode());
        if (num <= 0) {
            throw new PDAException("工单应发获取失败");
        }
        // 工单已发
        double rdNum = this.wareHouseMaterialMapper.selectmgRdByParam(barCodeEntity.getfOrderNo(),
                barCodeEntity.getfMatCode(), barCodeEntity.getfProcessCode());

        if (barCodeEntity.getfWeight() + rdNum > num) {
            throw new PDAException("该料号超ERP应发量！");
        }

        return null;
    }

    /**
     * 仓库发料公共方法
     *
     * @param packMessage
     * @return
     */
    private String wareHouseMAterialCommon(PackMessage packMessage, BarCodeEntity barCodeEntity) {
        BigDecimal dlwater = new BigDecimal(barCodeEntity.getDlwater());
        BigDecimal fWeight = new BigDecimal(barCodeEntity.getfWeight());
        // 查询领料申请
        int flagCount = this.wareHouseMaterialMapper.countRecmat(barCodeEntity.getfPlanID());
        if (flagCount <= 0) {
            throw new PDAException("领料申请不存在！");
        }
        // 查询历史实发量
        BigDecimal frspqty = this.wareHouseMaterialMapper.selectFrspqtyByplanid(barCodeEntity.getfPlanID());
        if ("领料".equals(barCodeEntity.getfType())) {
            if (fWeight.subtract(dlwater.subtract(frspqty)).intValue() > 0) {
                throw new PDAException("实发量不能大于该领料申请的欠量");
            }
        }
        // 查询数据源
        String dataSource = queryDataSource(packMessage);
        // 查询erp库存
        double stock = this.wareHouseMaterialMapper.selectErpStock(dataSource, barCodeEntity.getfMatCode(),
                barCodeEntity.getfWareCode(), barCodeEntity.getfSeatCode());
        if (barCodeEntity.getfWeight() > stock) {
            throw new PDAException("ERP库存不足此笔发料");
        }
        // 接口数量
        double xfQty = this.wareHouseMaterialMapper.selectXfSumByParam(barCodeEntity.getfMatCode(),
                barCodeEntity.getfWareCode(), barCodeEntity.getfSeatCode());


        // 历史未交接量-
        double hisQty = this.wareHouseMaterialMapper.countRecMateHisQtyByParms(barCodeEntity.getfMatCode(),
                barCodeEntity.getfWareCode(), barCodeEntity.getfSeatCode());

        if (barCodeEntity.getfWeight() + xfQty + hisQty > stock) {
            throw new PDAException("历史未交接量+本次CrashLog实发量+接口表数量>erp库存");
        }
        // 查询工单是否结案
        int count3 = this.wareHouseMaterialMapper.countsfbFlagByOrderNo(dataSource, barCodeEntity.getfOrderNo());

        if (count3 > 0) {
            throw new PDAException("工单已结案，不允许发料");
        }

        return "Y##";

    }


    /**
     * 查询数据源
     *
     * @param packMessage
     * @return
     */
    private String queryDataSource(PackMessage packMessage) {
        // 查询数据源
        String dbsource = this.wareHouseMaterialMapper.queryDataSource(packMessage.getUser().getsCode());

        if (StringUtil.isNotEmpty(dbsource)) {
            return dbsource;
        }

        return "DS2";
    }

}
